package com.youshang520i.thread;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author youshang
 * @date 2021/03/08 17:29
 **/
public class MyBlockingPractice {

    public static void main(String[] args) {
        Parameter parameter = new Parameter();
        for (int i = 0; i < 10; i++) {
            new Thread(new MyT1(parameter), "thread - MyT1 - " + i).start();
        }
        for (int i = 0; i < 10; i++) {
            new Thread(new MyT2(parameter), "thread - MyT2 - " + i).start();
        }
    }
}

class Parameter {
    public static Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue();
    Integer num = 0;

    public void add() {
        while (linkedBlockingQueue.size() == 10) {
            try {
                condition1.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        num++;
        String name = Thread.currentThread().getName();
        linkedBlockingQueue.add("add:    " + name + "     " + linkedBlockingQueue.size());
        System.out.println("add:    " + name + "     " + linkedBlockingQueue.size());
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        condition2.signal();
    }

    public void poll() {
        while (linkedBlockingQueue.size() == 0) {
            try {
                condition2.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Object poll = linkedBlockingQueue.poll();
        System.out.println("poll:   " + poll);
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        condition1.signal();
    }
}

class MyT1 implements Runnable {
    private Parameter parameter;

    public MyT1(Parameter parameter) {
        this.parameter = parameter;
    }

    @Override
    public void run() {
        try {
            parameter.lock.lock();
            while (true) {
                parameter.add();
            }
        } finally {
            parameter.lock.unlock();
        }
    }
}

class MyT2 implements Runnable {
    private Parameter parameter;

    public MyT2(Parameter parameter) {
        this.parameter = parameter;
    }

    @Override
    public void run() {
        try {
            parameter.lock.lock();
            while (true) {
                parameter.poll();
            }
        } finally {
            parameter.lock.unlock();
        }
    }
}

